﻿using System.Collections.Generic;
using CID.Domain.Users;
using NailsFramework.Persistence;
using CID.Domain.Exceptions;

namespace CID.Domain.Development
{
    public class Release : Model<Release>, IRelease
    {
        public virtual int Id { get; private set; }
        public virtual string Name { get; set; }
        public virtual string Description { get; set; }
        public virtual ReleaseStatus Status { get; private set; }
        public virtual IUser Responsible { get; set; }

        private IList<IVersion> versions = new List<IVersion>();
        public virtual IEnumerable<IVersion> Versions { get { return versions; } }

        protected Release()
        {
            Status = ReleaseStatus.Planned;
        }

        public Release(string name, string description, IUser responsible) : this()
        {
            Name = name;
            Description = description;
            Responsible = responsible;
        }

        #region Equals and GetHashCode
        //This class needs to have the Equals overriden to support the comparison with the proxies from the persistence layer
        public override bool Equals(object obj)
        {
            return EntityEqualityHelper.Equals(this, obj);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }
        #endregion

        public virtual void SetActive()
        {
            if (Status == ReleaseStatus.Released) throw new InvalidActionForReleaseStatusException("set Release as Active", ReleaseStatus.Released);
            Status = ReleaseStatus.Active;
        }

        public virtual void SetObsolete()
        {
            if (Status == ReleaseStatus.Released) throw new InvalidActionForReleaseStatusException("set Release as Obsolete", ReleaseStatus.Released);
            Status = ReleaseStatus.Obsolete;
        }

        public virtual void SetReleased()
        {
            if (Status == ReleaseStatus.Obsolete) throw new InvalidActionForReleaseStatusException("set Release as Released", ReleaseStatus.Obsolete);
            if (Status == ReleaseStatus.Planned) throw new InvalidActionForReleaseStatusException("set Release as Released", ReleaseStatus.Planned);
            Status = ReleaseStatus.Released;
        }

        public virtual void AddVersion(IVersion version)
        {
            if (Status == ReleaseStatus.Released) throw new InvalidActionForReleaseStatusException("add Version", ReleaseStatus.Released);
            if (Status == ReleaseStatus.Obsolete) throw new InvalidActionForReleaseStatusException("add Version", ReleaseStatus.Obsolete);

            if (!versions.Contains(version))
            {
                version.SetRelease(this);
                versions.Add(version);
            }
        }

        public virtual void RemoveVersion(IVersion version)
        {
            if (Status == ReleaseStatus.Released) throw new InvalidActionForReleaseStatusException("remove Version", ReleaseStatus.Released);

            if (Equals(version.Release))
            {
                version.ResetRelease();
                versions.Remove(version);
            }
        }
    }
}
